package lowijs.XfireClient.packet;

import java.nio.*;

public abstract class Packet {
	private final ByteBuffer buf = ByteBuffer.allocate(8192);
	
	public Packet() {
		buf.position(2);
	}

	/**
	 * Puts a byte in the byte buffer.
	 * @param b the byte to put.
	 */
	protected void putByte(byte b) {
		buf.put(b);
	}
	
	/**
	 * Puts a byte[] in the byte buffer.
	 * @param bs the byte[] to put.
	 */
	protected void putBytes(byte[] bs) {
		buf.put(bs);
	}
	
	/**
	 * Sets the size of the packet in the first two bytes.
	 */
	protected void setSize() {
		int size = buf.position();
		
		buf.position(0);
		buf.put(toLowHigh(size));
		buf.position(size);
	}

	/**
	 * Converts an int into two bytes (low and high byte).
	 * @param num the number to convert.
	 * @return a byte[] { low, high }.
	 */
	protected static byte[] toLowHigh(int num) {
		byte[] result = new byte[] {
				(byte)(num & 0xFF),
				(byte)((num & 0xFF00) >> 8)
		};
		
		return result;
	}
	
	/**
	 * Converts two bytes (low and high byte) into an int.
	 * @param low the low byte.
	 * @param high the high byte.
	 * @return the int created from the low and high byte.
	 */
	protected static int fromLowHigh(byte low, byte high) {
		return 0x00 | (low & 0xFF) | ((high & 0xFF) << 8);
	}
	
	protected static byte[] toFourBytes(int num) {
		byte[] result = new byte[] {
				(byte)(num & 0xFF),
				(byte)((num & 0xFF00) >> 8),
				(byte)((num & 0xFF0000) >> 16),
				(byte)((num & 0xFF000000) >> 24)
		};
		
		return result;
	}
	
	/**
	 * Puts a string with length into the byte buffer.
	 * @param data the string to put.
	 */
	protected void putString(String data) {
		int length = data.length();
		
		if(length > 0xFF)
			putByte((byte)0x02);
		else
			putByte((byte)0x01);
		
		putBytes(toLowHigh(length));
		putBytes(data.getBytes());
	}
	
	protected void putShortString(String data) {
		putBytes(toLowHigh(data.length()));
		putBytes(data.getBytes());
	}
	
	protected static boolean isZero(byte[] bytes) {
		for (int i = 0; i < bytes.length; i++) {
			if ((bytes[i] & 0xFF) > 0)
				return false;
		}
		return true;
	}
	
	/**
	 * Returns the packet as an array of bytes.
	 * @return the packet as a byte[].
	 */
	public byte[] getBytes() {
		setSize();
		
		buf.flip();
		int size = buf.limit();
		
		byte[] bytes = new byte[size];
		buf.get(bytes, 0, size);
		
		return bytes;
	}
}
